import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import { Singleton, genGetInstance } from '../utils';

const Index = () => {
  const [showCode, setShowCode] = useState(false);
  // 1.创建对象
  useEffect(() => {
    var a = {
      method1: function () {
        // ...
      },
      method2: function () {
        // ...
      },
    };
  }, []);

  useEffect(() => {
    // const s1 = new Singleton();
    // Singleton.instance
    // console.log(s1);
    // console.log(Singleton.instance);
    
    // 创建实例
    // const s1 = Singleton.getInstance();
    // const s2 = Singleton.getInstance();
    // console.log(s1);
    // console.log(s1 === s2); // true
  }, []);

  /** 闭包方式 */
  useEffect(() => {
    const getInstance = genGetInstance();

    const s1 = getInstance();
    const s2 = getInstance();
    // console.log(s1 === s2); // true
  }, []);

  const str = `
  class Singleton {
    // private - 外部无法初始化
    private constructor() {}

    // static 属性
    private static instance: Singleton | null;

    // static 方法
    static getInstance(): Singleton {
      if (Singleton.instance == null) {
        Singleton.instance = new Singleton();
      }
      return Singleton.instance;
    }
  }`;

  const str1 = `
  /** 闭包方式 */
  function genGetInstance() {
    let instance: any; // 闭包

    class Singleton {}

    return () => {
      if (instance == null) {
        instance = new Singleton();
      }
      return instance;
    };
  }`;
  return (
    <div>
      <h3>
        单例模式（Singleton）的目的是为了保证在一个进程中，某个类有且仅有一个实例。
        因为这个类只有一个实例，因此，自然不能让调用方使用new
        Xyz()来创建实例了。所以，单例的构造方法必须是private，这样就防止了调用方自己创建实例，但是在类的内部，是可以用一个静态字段来引用唯一创建的实例的：
      </h3>
      <pre style={{ background: '#eee', padding: 20 }}>
        {`
  class Singleton {
    // private - 外部无法初始化
    private constructor() {}

    // static 属性
    private static instance: Singleton | null;
  }`}
      </pre>
      <h3>那么问题来了，外部调用方如何获得这个唯一实例？</h3>
      <pre style={{ background: '#eee', padding: 20 }}>
        {`
  class Singleton {
    // private - 外部无法初始化
    private constructor() {}

    // static 属性
    private static instance: Singleton | null;
    // static 方法
    static getInstance(): Singleton {
      if (Singleton.instance == null) {
        Singleton.instance = new Singleton();
      }
      return Singleton.instance;
    }
  }`}
      </pre>
      <h3>单例模式的实现方式核心：</h3>
      <ul>
        <li>private构造方法，确保外部无法实例化；</li>
        <li>通过private static变量持有唯一实例，保证全局唯一性；</li>
        <li>通过 static方法返回此唯一实例，使外部调用方能获取到实例。</li>
      </ul>
      <Button
        style={{ margin: '20 0' }}
        type="link"
        onClick={() => setShowCode(!showCode)}
      >
        {showCode ? '隐藏代码' : '展示代码'}
      </Button>
      {showCode && (
        <>
          <pre style={{ background: '#eee', padding: 20 }}>{str}</pre>
          <pre style={{ background: '#eee', padding: 20 }}>{str1}</pre>
        </>
      )}
    </div>
  );
};
export default Index;
